<template>
    <el-row class="login-body" type="flex" justify="center">
        <!-- 二维码区域 采用了动态布局详见 element plus官网-->
        <el-col :xl="6" :lg="7">
            <h2>闲人沽酒-管理系统</h2>
            <el-image :src="require('@/assets/二维码.png')"></el-image>
            <p>牡丹低眉笑人事</p>
            <p>闲人沽酒洛阳东</p>
        </el-col>

        <!-- 分割线区域 -->
        <el-col :span="1">
            <el-divider direction="vertical" />
        </el-col>

        <!-- 表单区域 xl lg 采用动态布局-->
        <el-col :xl="6" :lg="7">
            <div>
                <!-- v-model绑定js中表单对象 rules表单验证的规则-->
                <!-- ref 讲表单注册一个实例，可以通过loginFormRef  js或ts中就可以通过实例调用这个对象 -->
                <el-form ref="loginFormRef" :model="loginForm" :rules="rules" label-width="80px" class="demo-loginForm"
                    :size="formSize" status-icon>
                    <el-form-item label="用户名" prop="userName" style="width: 380px;">
                        <el-input v-model="loginForm.username" />
                    </el-form-item>
                    <el-form-item label="密码" prop="password" style="width: 380px;">
                        <el-input v-model="loginForm.password" />
                    </el-form-item>
                    <el-form-item label="验证码" prop="code" style="width: 380px;">
                        <el-input v-model="loginForm.code" style="width: 172px; float: left" maxlength="5" />

                        <!-- 验证码图片 -->
                        <el-image :src="captchaImg" class="captchaImg" @click="getCaptcha"></el-image>
                    </el-form-item>

                    <!-- 提交重置按钮 -->
                    <el-form-item>
                        <!-- 点击按钮传入一个表单ref的实例 -->
                        <el-button type="primary" @click="submitForm(loginFormRef)">登录</el-button>
                        <el-button @click="resetForm(loginFormRef)">重置</el-button>
                    </el-form-item>
                </el-form>
            </div>
        </el-col>
    </el-row>
</template>

<script setup lang="ts">
// 导入 Vue 3 的 ref 和 reactive 方法
import { getCurrentInstance, reactive, ref, onMounted } from 'vue';
// 导入 Element-Plus 表单相关的类型
import { type FormInstance, type FormRules } from 'element-plus';
import { useStore } from 'vuex';
import { useRoute, useRouter } from 'vue-router';
import qs from 'qs';
// import store from '@/store';
// import router from '@/router';

// 获取全局引用的依赖

// 获取axios实例 由于setup中不能使用this，因此需要使用getCurrentInstance 方法获得当前活跃的组件
const { proxy } = (getCurrentInstance() as any);
// 获取store实例
const store = useStore();
// 获取router实例
const router = useRouter();
// 获取当前路由
const route = useRoute();

// 获取验证码图片
const captchaImg = ref('');
function getCaptcha() {
    proxy.$axios.get('/captcha').then(function (res: any) {
        // 后端返回 一个token  一个图片验证码
        loginForm.token = res.data.data.token; // 对应后端的token
        captchaImg.value = res.data.data.captchaImg;
        loginForm.code = ''; // 清空验证码输入框
    })
}

// 定义登录表单的数据结构 使用接口关键字 只是定义 不实现实例化
interface LoginForm {
    username: string
    password: string
    code: string
    token: string
}
const formSize = ref('default'); // 表单大小，默认为 'default'
// 创建登录表单实例的 ref
const loginFormRef = ref<FormInstance>();
// 使用 reactive 创建响应式的登录表单数据 实现了表单的双向绑定 决定后端收到的值
const loginForm = reactive<LoginForm>({
    /**模拟登陆，先给一个默认数据 正确的用户名 */
    username: 'admin',  // 用户名
    password: '111111',  // 密码
    code: '11111',      // 验证码
    token: 'aaaaa', // 随机码
});

// 使用 reactive 创建表单验证规则
const rules = reactive<FormRules<LoginForm>>({
    username: [
        { required: true, message: '请输入用户名', trigger: 'blur' },  // 用户名必填
    ],
    password: [
        { required: true, message: '请输入密码', trigger: 'blur' },  // 密码必填
    ],
    code: [
        { required: true, message: '请输入验证码', trigger: 'blur' },  // 验证码必填
        { min: 5, max: 5, message: '验证码长度为 5 个字符', trigger: 'blur' } // 长度验证
    ],
});

// 定义表单提交函数，接受表单实例作为参数
async function submitForm(formEl: FormInstance | undefined) {
    if (!formEl) {
        return;
    }

    // 使用表单实例的 validate 方法进行表单验证 函数包含验证结果和返回错误对象
    await formEl.validate(function (valid, fields) {
        if (valid) {            
            // 请求后端接口 给后端返回的是一个json数据
            // proxy.$axios.post('/login', loginForm).then(function (res: any) { // 之前的提交方式是一个json格式的
            proxy.$axios.post('/login?' + qs.stringify(loginForm)).then((res: any) => { // 转换为老版的form提交方式，url数据传输
                // 登录成功后，从响应头中获取 JWT，并存储到 Vuex 中

                // 问： 什么是JWT，能干什么？
                // JWT 用户一次登录，生成类似令牌的JWT 贯穿后续请求的用户信息

                // 问： 为什么使用头部的 authorization成为JWT？
                // 使用Authorization头部是一种推荐的方式，有助于确保JWT的传输安全、标准化，并与各种后端框架和认证机制保持兼容。
                const jwt = res.headers['authorization'];
                /**
                 * 问：commit函数的作用是什么？
                 * 
                 * 在 Vuex 中，store.commit 是用于触发 mutations 的方法。
                 * 在你提到的代码中，store.commit('SET_TOKEN', jwt) 的作用是触发名为 SET_TOKEN 的 mutation，并将 jwt 作为参数传递给该 mutation。
                 * 具体来说，store.commit 接收两个参数：
                 * 1、Mutation 名称（String）： 这是你在 Vuex store 中定义的 mutation 的名称。
                 * 在你的例子中，是 'SET_TOKEN'。
                 * 2、Payload（任意类型）： 这是传递给 mutation 的参数，用于修改状态。
                 * 在你的例子中，jwt 是作为 payload 传递给 SET_TOKEN mutation。
                 * 
                 * 这行代码的作用是通知 Vuex store 执行名为 SET_TOKEN 的 mutation，并将 jwt 作为参数传递给这个 mutation。
                 * 这样可以在 mutation 中修改 Vuex store 中的状态，例如更新 token 的值，并在整个应用中保持状态同步。
                 */
                store.commit('SET_TOKEN', jwt);
                // 跳转到首页
                router.push('/index');
            });
        } else {
            console.log('提交失败！', fields);
        }
    });
}

// 定义表单重置函数，接受表单实例作为参数
function resetForm(formEL: FormInstance | undefined) {
    if (!formEL) {
        return;
    }
    formEL.resetFields(); // 表单重置
}

onMounted(() => {
    getCaptcha();
});
</script>

<style scoped>
.login-body {
    background-color: #fafafa;
    /* 采用绝对定位 实现居中 */
    position: fixed;
    height: 100%;
    width: 100%;
    align-items: center;
    text-align: center;
    justify-content: center;
}

.el-divider {
    height: 200px;
}

.captchaImg {
    float: left;
    margin-left: 8px;
    border-radius: 4px;
    /*圆角*/
}
</style>